﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;

namespace Utilities.Media.Documents
{
    public class ICalendar
    {
        public class Block
        {
            protected static string DtFormat = "yyyyMMddTHHmmss";
            protected static CultureInfo Culture = new CultureInfo("fr-FR");

            public string Name { get; protected set; }

            protected Dictionary<string, string> Properties = new Dictionary<string, string>();
            protected List<Block> Blocks = new List<Block>();

            public Block(StreamReader reader, string name)
            {
                Name = name;

                while (!reader.EndOfStream)
                {
                    string line = reader.ReadLine();

                    string propertyName = line.Remove(line.IndexOf(':')).Trim();
                    string propertyValue = line.Substring(line.IndexOf(':') + 1).Trim();

                    if (propertyName == "BEGIN")
                    {
                        switch (propertyValue)
                        {
                            case "VCALENDAR": Blocks.Add(new Calendar(reader)); break;
                            case "VEVENT": Blocks.Add(new Event(reader)); break;

                            default: Blocks.Add(new Block(reader, propertyValue)); break;
                        }
                    }
                    else if (propertyName == "END")
                        break;
                    else
                        Properties.Add(propertyName, propertyValue);
                }
            }
        }
        public class Calendar : Block
        {
            public string Version
            {
                get
                {
                    return Properties.ContainsKey("VERSION") ? Properties["VERSION"] : null;
                }
            }
            public string ProdId
            {
                get
                {
                    return Properties.ContainsKey("PRODID") ? Properties["PRODID"] : null;
                }
            }

            public List<Event> Events
            {
                get
                {
                    return Blocks.OfType<Event>().ToList();
                }
            }

            public Calendar(StreamReader reader) : base(reader, "VCALENDAR")
            {
            }
        }
        public class Event : Block
        {
            public string UId
            {
                get
                {
                    return Properties.ContainsKey("UID") ? Properties["UID"] : null;
                }
            }
            public DateTime DtStart
            {
                get
                {
                    return Properties.ContainsKey("DTSTART") ? DateTime.ParseExact(Properties["DTSTART"], DtFormat, Culture) : default(DateTime);
                }
            }
            public DateTime DtEnd
            {
                get
                {
                    return Properties.ContainsKey("DTEND") ? DateTime.ParseExact(Properties["DTEND"], DtFormat, Culture) : default(DateTime);
                }
            }
            public string Location
            {
                get
                {
                    return Properties.ContainsKey("LOCATION") ? Properties["LOCATION"] : null;
                }
            }
            public string Categories
            {
                get
                {
                    return Properties.ContainsKey("CATEGORIES") ? Properties["CATEGORIES"] : null;
                }
            }
            public string Summary
            {
                get
                {
                    return Properties.ContainsKey("SUMMARY") ? Properties["SUMMARY"] : null;
                }
            }

            public Event(StreamReader reader) : base(reader, "VEVENT")
            {
            }

            public override string ToString()
            {
                return DtStart.ToString() + " : " + Summary;
            }
        }

        private Calendar calendar;

        public List<Event> Events
        {
            get
            {
                return calendar.Events;
            }
        }

        public ICalendar(string path)
        {
            StreamReader reader = new StreamReader(path);
            string line = reader.ReadLine();

            calendar = new Calendar(reader);
        }

        public Event GetEventAt(DateTime dateTime)
        {
            return calendar.Events.SingleOrDefault(e => e.DtStart < dateTime && e.DtEnd > dateTime);
        }
    }
}
